#include "MyMongoC.h"


MyMongoC::MyMongoC()
{
    m_client = NULL;
    m_db = NULL;
    mongoc_init();
}

MyMongoC::~MyMongoC()
{
    Destroy();
    mongoc_cleanup();
}

//连接
bool MyMongoC::Connect(const char* ip, int port, const char* db, const char* user, const char* pwd)
{

    std::lock_guard<std::mutex> lock(m_mutex);

    //销毁
    Destroy();

    //uri
    std::string strUri;
    if(user != NULL)
    {
        strUri = "mongodb://" + std::string(user) + ":" + pwd + "@" + ip + ":" + std::to_string(port) + "/" + db;
    }
    else
    {
        strUri = "mongodb://" + std::string(ip) + ":" + std::to_string(port);
    }

    m_strDB = db;
    //判断uri是否错误
    mongoc_uri_t* uri = mongoc_uri_new_with_error(strUri.c_str(), &m_error);
    if(uri == NULL)
    {
        std::cout << "mongoc_uri_new_with_error err: " << m_error.message << std::endl;
        return false;
    }

    //根据uri创建client
    m_client = mongoc_client_new_from_uri(uri);
    if(m_client == NULL)
    {
        std::cout << "mongoc_client_new_from_uri err"<< std::endl;
        //释放uri
        mongoc_uri_destroy(uri);
        return false;
    }

    //释放uri
    mongoc_uri_destroy(uri);

    //获取数据库
    m_db = mongoc_client_get_database(m_client, db);
    if(m_db == NULL)
    {
        std::cout << "mongoc_client_get_database err: " << m_error.message << std::endl;
        return false;
    }

    // 执行命令操作(ping)
    bson_t* command = BCON_NEW ("ping", BCON_INT32 (1));
    bson_t* reply;

    bool ret = mongoc_client_command_simple (m_client, m_strDB.c_str(), command, NULL, reply, &m_error);
    if (ret == false) 
    {
        std::cout << "mongoc_client_command_simple err: " << m_error.message << std::endl;
        return false;
    }

    // 获取json形式的结果
    char* str = bson_as_json (reply, NULL);

    //打印输出
    std::cout << str << std::endl;

    bson_destroy (reply);
    bson_destroy (command);
    bson_free (str);

    return true;
}


//插入
bool MyMongoC::Insert(const char* collection, bson_t* command)
{
    
    std::lock_guard<std::mutex> lock(m_mutex);

    //获取文档
    mongoc_collection_t* _collection = mongoc_client_get_collection(m_client, m_strDB.c_str(), collection);
    if(_collection == NULL)
    {
        std::cout << "mongoc_client_get_collection err" << std::endl;
        return false;
    }

    //插入
    bool ret = mongoc_collection_insert(_collection, MONGOC_INSERT_NONE, command, NULL, &m_error);
    if(ret == false)
    {
        std::cout << "mongoc_collection_insert err: " << m_error.message << std::endl;

        //释放文档
        mongoc_collection_destroy(_collection);
        return false;
    }

    //释放文档
    mongoc_collection_destroy(_collection);

    return true;
}

//查询
mongoc_cursor_t* MyMongoC::Query(const char* collection, bson_t* conditions = NULL, bson_t* query, int skip, int limit)
{
    
    std::lock_guard<std::mutex> lock(m_mutex);

    //获取文档
    mongoc_collection_t* _collection = mongoc_client_get_collection(m_client, m_strDB.c_str(), collection);
    if(_collection == NULL)
    {
        std::cout << "mongoc_client_get_collection err" << std::endl;
        return NULL;
    }

    //查询
    mongoc_cursor_t* cursor = mongoc_collection_find(_collection, MONGOC_QUERY_NONE, skip, limit, 0, conditions, query, NULL);
    if(cursor == NULL)
    {
        std::cout << "mongoc_collection_find err" << std::endl;

        //释放文档
        mongoc_collection_destroy(_collection);
        return NULL;
    }

    //释放文档
    mongoc_collection_destroy(_collection);

    //返回游标
    return cursor;
}

//更新
bool MyMongoC::Update(const char* collection, bson_t* conditions, bson_t* update)
{
    
    std::lock_guard<std::mutex> lock(m_mutex);

    //获取文档
    mongoc_collection_t* _collection = mongoc_client_get_collection(m_client, m_strDB.c_str(), collection);
    if(_collection == NULL)
    {
        std::cout << "mongoc_client_get_collection err" << std::endl;
        return false;
    }

    //更新文档
    if(mongoc_collection_update(_collection, MONGOC_UPDATE_NONE, conditions, update, NULL, &m_error) == false)
    {
        std::cout << "mongoc_collection_update err: " << m_error.message << std::endl;

        //释放文档
        mongoc_collection_destroy(_collection);
        return false;
    }

    //释放文档
    mongoc_collection_destroy(_collection);

    return true;
}

//删除
bool MyMongoC::Delete(const char* collection, bson_t* conditions)
{

    std::lock_guard<std::mutex> lock(m_mutex);

    //获取文档
    mongoc_collection_t* _collection = mongoc_client_get_collection(m_client, m_strDB.c_str(), collection);
    if(_collection == NULL)
    {
        std::cout << "mongoc_client_get_collection err" << std::endl;
        return false;
    }

    //删除文档
    if(mongoc_collection_remove(_collection, MONGOC_REMOVE_NONE, conditions,  NULL, &m_error) == false)
    {
        std::cout << "mongoc_collection_remove err: " << m_error.message << std::endl;

        //释放文档
        mongoc_collection_destroy(_collection);
        return false;
    }

    //释放文档
    mongoc_collection_destroy(_collection);


    return true;
}

//统计
int64_t MyMongoC::Count(const char* collection, bson_t* conditions, int skip, int limit)
{
    
    std::lock_guard<std::mutex> lock(m_mutex);

    //获取文档
    mongoc_collection_t* _collection = mongoc_client_get_collection(m_client, m_strDB.c_str(), collection);
    if(_collection == NULL)
    {
        std::cout << "mongoc_client_get_collection err" << std::endl;
        return -1;
    }

    //统计文档
    int64_t nCount = mongoc_collection_count(_collection, MONGOC_QUERY_NONE, conditions, skip, limit, NULL, &m_error);
    if(nCount < 0)
    {
        std::cout << "mongoc_collection_count err: " << m_error.message << std::endl;

        //释放文档
        mongoc_collection_destroy(_collection);
        return -1;
    }

    //释放文档
    mongoc_collection_destroy(_collection);

    return nCount;
}

//销毁成员变量
void MyMongoC::Destroy()
{
    m_strDB.clear();

    if(m_db != NULL)
    {
        mongoc_database_destroy(m_db);
        m_db = NULL;
    }
    if(m_client != NULL)
    {
        mongoc_client_destroy(m_client);
        m_client = NULL;
    }
}
